/* The file is part of the Waff web framework.
 *
 * Copyright (c) 2011, Grzegorz Skorupa
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditionsare met:
 *
 * - Redistributions of source code must retain the above copyright notice, this list of conditions
 *   and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 *   and the following disclaimer in the documentation and/or other materials provided with the distribution.
 * - Neither the name of the Grzegorz Skorupa nor the names of its contributors may be used to endorse or promote products
 *   derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package pl.org.waff;

import javax.servlet.http.*;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.HashSet;
import java.util.logging.Logger;

/**
 *
 * @author greg
 */
public class DefaultSecurityManager implements SecurityManager {

    private static Properties properties;
    private static final Logger log = Logger.getLogger(DefaultSecurityManager.class.getName());
    private static String standardDevicePrefix;
    private static String mobileDevicePrefix;
    private static boolean mobileHandling = false;

    public void init(Properties newproperties, String mobileDeviceHandling, String standardDevicePrefix, String mobileDevicePrefix) {
        properties = (Properties) newproperties.clone();
        mobileHandling = Boolean.parseBoolean(mobileDeviceHandling);
        this.standardDevicePrefix = standardDevicePrefix;
        this.mobileDevicePrefix = mobileDevicePrefix;
    }

    private boolean match(String groups, HashSet roles) {
        boolean ret = false;
        if (null != groups && groups.length() > 0 && !roles.isEmpty()) {
            StringTokenizer st = new StringTokenizer(groups, ",");
            String roleName;
            while (st.hasMoreTokens() && !ret) {
                roleName = st.nextToken();
                ret = roles.contains(roleName);
            }
        }
        return ret;
    }

    /**
     * Checks user's access to the web application path
     * @param pathName
     * @param req request object
     * @param navigator
     * @return 
     */
    public boolean pathAccessible(String pathName, HttpServletRequest req, SiteNavigator navigator) {
        log.fine(pathName);
        boolean ret = false;
        PathElement pe;
        String prefix = (String) req.getSession().getAttribute(WaffServlet.PATH_PREFIX_ATTRIBUTE_NAME);

        pe = navigator.getPathData(pathName, prefix);
        if (pe == null) {
            return false;
        }
        String groups = pe.getPolicy();
        User user = (User) req.getSession().getAttribute("waffuser");
        if (null == groups || groups.isEmpty()) {
            groups = "*";
        }
        if ("*".equals(groups)) {
            ret = true;
        } else if (user != null) {
            ret = match(groups, user.getRoles());
        }
        return ret;
    }

    /**
     * Check user's rights to an object
     * @param objectName
     * @param accessibleByDefault 
     * @param req request object
     * @return 
     */
    public boolean objectAccessible(String objectName, boolean accessibleByDefault, HttpServletRequest req) {
        boolean ret = false;
        User user = (User) req.getSession().getAttribute("waffuser");
        String groups = properties.getProperty(objectName + ".access");
        if (null == groups && accessibleByDefault) {
            groups = "*";
        }
        if ("*".equals(groups)) {
            ret = true;
        } else if (user != null) {
            ret = match(groups, user.getRoles());
        }
        return ret;
    }

    /**
     * Check user's rights to object's method
     * @param objectName
     * @param methodName
     * @param accessibleByDefault
     * @param req
     * @return 
     */
    public boolean objectMethodAccessible(String objectName, String methodName, boolean accessibleByDefault, HttpServletRequest req) {
        boolean ret = false;
        String groups = "";
        String setterGroups;
        User user = (User) req.getSession().getAttribute("waffuser");
        if (methodName.startsWith("set")) {
            groups = properties.getProperty(objectName + ".access." + methodName);
            if (null == groups) {
                setterGroups = properties.getProperty(objectName + ".access." + "set*");
                if (null != setterGroups) {
                    groups = setterGroups;
                } else {
                    groups = "*";
                }
            }
        } else {
            groups = properties.getProperty(objectName + ".access." + methodName);
        }
        if (null == groups) {
            return objectAccessible(objectName, accessibleByDefault, req);
        }

        if ("*".equals(groups)) {
            ret = true;
        } else if (user != null) {
            ret = match(groups, user.getRoles());
        }
        return ret;
    }
}
